package org.example.rzfx.task;

import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.example.rzfx.entity.Log;
import org.example.rzfx.entity.LogParseRule;
import org.example.rzfx.entity.LogSource;
import org.example.rzfx.mapper.LogParseRuleMapper;
import org.example.rzfx.service.CollectMonitorService;
import org.example.rzfx.service.LogService;
import org.example.rzfx.service.LogSourceService;
import org.example.rzfx.util.FileReaderUtil;
import org.example.rzfx.util.LogParseUtil;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

/**
 * 日志采集定时任务
 */
@Component
@Slf4j
public class LogCollectTask {
    
    @Resource
    private LogSourceService logSourceService;
    
    @Resource
    private LogService logService;
    
    @Resource
    private CollectMonitorService collectMonitorService;
    
    @Resource
    private LogParseRuleMapper logParseRuleMapper;
    
    /**
     * 文件日志采集任务（每分钟执行一次）
     */
    @Scheduled(cron = "0 * * * * ?")
    public void collectFileLogs() {
        log.info("开始执行文件日志采集任务...");
        
        // 查询所有启用的文件采集源
        LambdaQueryWrapper<LogSource> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(LogSource::getSourceType, "file")
               .eq(LogSource::getStatus, 1);
        List<LogSource> sources = logSourceService.list(wrapper);
        
        for (LogSource source : sources) {
            try {
                collectFromFileSource(source);
            } catch (Exception e) {
                log.error("采集文件日志失败: " + source.getSourceName(), e);
                collectMonitorService.incrementFail(source.getId(), e.getMessage());
            }
        }
        
        log.info("文件日志采集任务完成");
    }
    
    /**
     * 从文件采集源采集日志
     */
    private void collectFromFileSource(LogSource source) throws Exception {
        // 解析配置
        JSONObject config = JSON.parseObject(source.getConfig());
        String filePath = config.getString("filePath");
        String charset = config.getString("charset");
        Long parseRuleId = config.getLong("parseRuleId");
        
        // 获取解析规则
        LogParseRule parseRule = null;
        if (parseRuleId != null) {
            parseRule = logParseRuleMapper.selectById(parseRuleId);
        }
        
        // 读取新增日志行
        long lastOffset = source.getLastOffset() != null ? source.getLastOffset() : 0L;
        List<String> newLines = FileReaderUtil.readNewLines(filePath, lastOffset);
        
        log.info("采集源[{}]读取到{}条新日志", source.getSourceName(), newLines.size());
        
        // 处理每一行日志
        for (String line : newLines) {
            try {
                processLogLine(source, line, parseRule);
                collectMonitorService.incrementSuccess(source.getId());
            } catch (Exception e) {
                log.error("处理日志行失败: " + line, e);
                collectMonitorService.incrementFail(source.getId(), e.getMessage());
            }
        }
        
        // 更新偏移量
        if (!newLines.isEmpty()) {
            long newOffset = FileReaderUtil.getFileSize(filePath);
            logSourceService.updateOffset(source.getId(), newOffset);
        }
        
        // 更新心跳
        logSourceService.updateHeartbeat(source.getId());
    }
    
    /**
     * 处理单行日志
     */
    private void processLogLine(LogSource source, String line, LogParseRule parseRule) {
        Log log = new Log();
        log.setSourceId(source.getId());
        log.setContent(line);
        log.setTimestamp(LocalDateTime.now());
        
        // 使用解析规则提取字段
        if (parseRule != null) {
            Map<String, String> fields = LogParseUtil.parseLog(line, parseRule);
            
            // 提取时间戳
            if (fields.containsKey("timestamp")) {
                try {
                    LocalDateTime timestamp = LocalDateTime.parse(
                        fields.get("timestamp").replace("T", " ").replace("Z", ""),
                        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")
                    );
                    log.setTimestamp(timestamp);
                } catch (Exception e) {
                    // 解析失败，使用当前时间
                }
            }
            
            // 提取日志级别
            if (fields.containsKey("level")) {
                log.setLogLevel(fields.get("level"));
            }
            
            // 存储提取的字段
            log.setFields(JSON.toJSONString(fields));
        }
        
        // 如果没有提取到日志级别，尝试从内容中提取
        if (log.getLogLevel() == null) {
            log.setLogLevel(LogParseUtil.extractLogLevel(line));
        }
        
        // 设置系统类型
        log.setSystemType(parseRule != null ? parseRule.getSystemType() : "UNKNOWN");
        
        // 生成唯一hash
        String uniqueHash = MD5.create().digestHex(line + log.getTimestamp().toString());
        log.setUniqueHash(uniqueHash);
        
        // 保存日志
        logService.saveLog(log);
    }
}

